#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "gtest/gtest.h"
#include "oj_common/oj_code_file.h"
#include "oj_common/oj_log.h"
#include "oj_common/oj_transfer.h"
#include "oj_compile_run/oj_compiler.h"
#include "oj_compile_run/oj_runer.h"
#include "oj_compile_run/oj_compile_run.h"
#include "oj_server/oj_server.h"

//                   _ooOoo_
//                  o8888888o
//                  88" . "88
//                  (| -|- |)
//                  O\  =  /O
//               ____/`---'\____
//             .'  \\|     |//  `.
//            /  \\|||  :  |||//  、
//           /  _||||| -:- |||||-  、
//           |   | \\\  -  /// |   |
//           | \_|  ''\---/''  |   |
//           \  .-\__  `-`  ___/-. /
//         ___`. .'  /--.--\  `. . __
//      ."" '<  `.___\_<|>_/___.'  >'"".
//     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//     \  \ `-.   \_ __\ /__ _/   .-` /  /
//      `-.____`-.___\_____/___.-`____.-'
//                   `=---='

// 清理上次项目运行残留文件
void Clean() {
    using namespace ojlb::oj_common;
    OjLog::info("清理上次项目运行残留文件");
    system("rm -f ./tests/user.c");
    system("rm -f ./tests/user.cout");
    system("rm -f ./tests/user.cerr");
    system("rm -f ./tests/user.cres");
    system("rm -f ./tests/user.cc");
    system("rm -f ./tests/user.ccout");
    system("rm -f ./tests/user.ccerr");
    system("rm -f ./tests/user.ccres");
    system("rm -f ./tests/User.java");
    system("rm -f ./tests/User.class");
    system("rm -f ./tests/User.javaerr");
    system("rm -f ./tests/User.javares");
}

// 模拟用户提交新的合法代码
void Creat() {
    using namespace ojlb::oj_common;
    Clean();
    OjLog::info("模拟用户提交新的合法代码");
    system("echo '#include<stdio.h>\n int main() { printf(\"Hello, C User!\"); return 0; }' > ./tests/user.c");
    system("echo '#include<iostream>\n int main() { std::cout << \"Hello, Cpp User!\"; return 0; }' > ./tests/user.cc");
    system("echo 'public class User { public static void main(String[] args) { System.out.print(\"Hello, Java User!\"); } }' > ./tests/User.java");
}

// 模拟用户代码中有编译错误
void CreatComError() {
    using namespace ojlb::oj_common;
    Creat();
    OjLog::info("模拟用户代码中有编译错误");
    system("echo 'a bug' >> ./tests/user.c");
    system("echo 'a bug' >> ./tests/user.cc");
    system("echo 'a bug' >> ./tests/User.java");
}

// 模拟用户代码中有运行错误(除零错误)
void CreatRunError() {
    using namespace ojlb::oj_common;
    Clean();
    OjLog::info("模拟用户代码中有运行错误");
    system("echo '#include <stdio.h>\nint main() { int a = 1; int b = 0; int c = a / b; printf(\"Hello, C User!\"); return 0; }' > ./tests/user.c");
    system("echo '#include <iostream>\nint main() { int a = 1; int b = 0; int c = a / b; std::cout << \"Hello, Cpp User!\" << std::endl; return 0; }' > ./tests/user.cc");
    system("echo 'public class User { public static void main(String[] args) { int a = 1; int b = 0; int c = a / b; System.out.println(\"Hello, Java User!\"); } }' > ./tests/User.java");
}

// 模拟用户代码中有内存限制
void CreatMemoryLimited() {
    using namespace ojlb::oj_common;
    Clean();
    OjLog::info("模拟用户代码中有内存限制");

    std::string c_code = "echo '";
    c_code += R"(#include <stdio.h>
#include <stdlib.h>
int main() {
    while (1) {
        char* p = (char*)malloc(5 * 1024 * 1024 * sizeof(char));
        if (p == NULL) {
            fprintf(stderr, "malloc error");
            break;
        }
    }
})";
    c_code += "' > ./tests/user.c";
    system(c_code.c_str());

    std::string cpp_code = "echo '";
    cpp_code += R"(#include <iostream>
int main() {
    while (true) {
        try {
            char* p = new char[1024 * 1024 * 5];
        } catch (std::bad_alloc& e) {
            std::cerr << "Memory allocation failed: " << e.what();
            break;
        }
    }
    return 0;
})";
    cpp_code += "' > ./tests/user.cc";
    system(cpp_code.c_str());

    std::string java_code = "echo '";
    java_code += R"(public class User {
    public static void main(String[] args) {
        try {
            long arraySize = Long.MAX_VALUE;
            byte[] largeArray = new byte[(int) arraySize];
            
            for (int i = 0; i < largeArray.length; i++) {
                largeArray[i] = 1;
            }
        } catch (OutOfMemoryError e) {
            System.err.println("Error: Not enough memory available to allocate the array.");
            e.printStackTrace();
            System.exit(1);
        }
    }
})";
    java_code += "' > ./tests/User.java";
    system(java_code.c_str());
}

// 模拟用户代码中有处理限制
void CreatCpuLimited() {
    using namespace ojlb::oj_common;
    Clean();
    OjLog::info("模拟用户代码中有处理限制");

    std::string c_code = "echo '";
    c_code += R"(#include <stdio.h>
#include <stdlib.h>
int main() {
    while(1);
})";
    c_code += "' > ./tests/user.c";
    system(c_code.c_str());

    std::string cpp_code = "echo '";
    cpp_code += R"(#include <iostream>
int main() {
    while(true);
})";
    cpp_code += "' > ./tests/user.cc";
    system(cpp_code.c_str());

    std::string java_code = "echo '";
    java_code += R"(public class User {
    public static void main(String[] args) {
        while(true) { int i = 0; }
    }
})";
    java_code += "' > ./tests/User.java";
    system(java_code.c_str());
}

// 将文件内容转化为 string
std::string ReadFileToString(const std::string& filePath) {
    std::fstream file(filePath);  // 打开文件
    if (!file.is_open()) {  // 检查文件是否成功打开
        std::cerr << "Could not open the file!" << std::endl;
        return "";
    }

    std::stringstream buffer;
    buffer << file.rdbuf();  // 将文件内容读入到字符串流中
    return buffer.str();  // 返回字符串流中的内容
}

TEST(OjClassTest, OjLog) {
    using namespace ojlb::oj_common;
    OjLog::setShieldLevel("trace");
    OjLog::trace("这是 trace");
    OjLog::debug("这是 debug");
    OjLog::info("这是 info");
    OjLog::warn("这是 warn");
    OjLog::error("这是 error {}", "message");
    OjLog::error("这是 error {}", std::string("hello"));
    OjLog::error("这是 error {} {} {}", 1, 2, 3);
}

TEST(OjClassTest, OjJson) {
    using namespace ojlb::oj_common;
    
    OjLog::info("创建一份 JSON 对象");
    Json::Value root;

    OjLog::info("添加一个普通键值对");
    root["name"] = "John";
    root["age"] = 30;
    root["isStudent"] = true;
    root["email"] = Json::nullValue;

    OjLog::info("添加一个数组");
    Json::Value hobbies(Json::arrayValue);
    hobbies.append("reading");
    hobbies.append("music");
    root["hobbies"] = hobbies;

    OjLog::info("添加一个嵌套的 JSON 对象");
    Json::Value address;
    address["city"] = "New York";
    address["zipcode"] = "10001";
    root["address"] = address;

    OjLog::info("序列化 json->string 后匹配测试结果, 符合预期");
    std::string str;
    std::string root_to_str = "{\n\t\"address\" : \n\t{\n\t\t\"city\" : \"New York\",\n\t\t\"zipcode\" : \"10001\"\n\t},\n\t\"age\" : 30,\n\t\"email\" : null,\n\t\"hobbies\" : \n\t[\n\t\t\"reading\",\n\t\t\"music\"\n\t],\n\t\"isStudent\" : true,\n\t\"name\" : \"John\"\n}";
    std::string root_to_str_indentation = R"({"address":{"city":"New York","zipcode":"10001"},"age":30,"email":null,"hobbies":["reading","music"],"isStudent":true,"name":"John"})";
    
    OjLog::info("序列化 json->string 后匹配有压缩测试结果, 符合预期");
    OjTransfer::serialize(root, str, true);
    EXPECT_EQ(str, root_to_str_indentation);

    OjLog::info("序列化 json->string 后匹配非压缩测试结果, 符合预期");
    OjTransfer::serialize(root, str, false);
    EXPECT_EQ(str, root_to_str);

    OjLog::info("反序列化 string->json 后匹配测试结果, 符合预期");
    Json::Value new_root;
    OjTransfer::deserialize(str, new_root);
    EXPECT_NE(&new_root, &root);
    EXPECT_EQ(new_root, root);

    OjLog::info("将序列化结果写入文件中, 匹配文件中的文本结果, 符合预期");
    system("rm -f ./tests/test.json");
    OjTransfer::stringToFile(str, "./tests/test.json");

    OjLog::info("将文件中序列化结果读出, 匹配文件中的文本结果, 符合预期");
    std::string get_str;
    OjTransfer::fileToString("./tests/test.json", get_str);
    EXPECT_EQ(root_to_str, get_str);
}

TEST(OjClassTest, OjStreaEdirection) {
    using namespace ojlb::oj_common;
    OjLog::warn("OjStreaEdirection 等待后续测试, 因为有重构的打算...");
    // TODO: 之前简单测过, 但是不够严谨, 并且有重构的打算...
}

TEST(OjClassTest, OjCodeFile) {
    using namespace ojlb::oj_common;
    Clean();
    
    OjLog::info("创建 OjCodeFile 对象");
    OjCodeFile c_f("./tests/user", "c");
    OjCodeFile cpp_f("./tests/user", "cpp");
    OjCodeFile java_f("./tests/User", "java");

    OjLog::info("获取名字结果, 符合预期");
    EXPECT_EQ(c_f.getCodeFileName(), "./tests/user");
    EXPECT_EQ(cpp_f.getCodeFileName(), "./tests/user");
    EXPECT_EQ(java_f.getCodeFileName(), "./tests/User");

    OjLog::info("获取语言结果, 符合预期");
    EXPECT_EQ(c_f.getProgrammingLanguage(), "c");
    EXPECT_EQ(cpp_f.getProgrammingLanguage(), "cpp");
    EXPECT_EQ(java_f.getProgrammingLanguage(), "java");

    OjLog::info("获取版本结果, 符合预期");
    EXPECT_EQ(c_f.getVersion(), "");
    EXPECT_EQ(cpp_f.getVersion(), "");
    EXPECT_EQ(java_f.getVersion(), "");

    OjLog::info("获取源文件路径, 符合预期");
    EXPECT_EQ(c_f.getSourcePath(), "./tests/user.c");
    EXPECT_EQ(cpp_f.getSourcePath(), "./tests/user.cc");
    EXPECT_EQ(java_f.getSourcePath(), "./tests/User.java");

    OjLog::info("获取目标文件路径, 符合预期");
    EXPECT_EQ(c_f.getObjectPath(), "./tests/user.cout");
    EXPECT_EQ(cpp_f.getObjectPath(), "./tests/user.ccout");
    EXPECT_EQ(java_f.getObjectPath(), "./tests/User.class");

    OjLog::info("获取错误文件路径, 符合预期");
    EXPECT_EQ(c_f.getErrorPath(), "./tests/user.cerr");
    EXPECT_EQ(cpp_f.getErrorPath(), "./tests/user.ccerr");
    EXPECT_EQ(java_f.getErrorPath(), "./tests/User.javaerr");

    OjLog::info("获取结果文件路径, 符合预期");
    EXPECT_EQ(c_f.getResultPath(), "./tests/user.cres");
    EXPECT_EQ(cpp_f.getResultPath(), "./tests/user.ccres");
    EXPECT_EQ(java_f.getResultPath(), "./tests/User.javares");

    OjLog::info("用户源文件不存在, 符合预期");
    EXPECT_FALSE(c_f.isExistOfSourcePath());
    EXPECT_FALSE(cpp_f.isExistOfSourcePath());
    EXPECT_FALSE(java_f.isExistOfSourcePath());

    OjLog::info("用户目标文件不存在, 符合预期");
    EXPECT_FALSE(c_f.isExistOfObjectPath());
    EXPECT_FALSE(cpp_f.isExistOfObjectPath());
    EXPECT_FALSE(java_f.isExistOfObjectPath());

    OjLog::info("用户错误文件不存在, 符合预期");
    EXPECT_FALSE(c_f.isExistOfErrorPath());
    EXPECT_FALSE(cpp_f.isExistOfErrorPath());
    EXPECT_FALSE(java_f.isExistOfErrorPath());

    OjLog::info("用户结果文件不存在, 符合预期");
    EXPECT_FALSE(c_f.isExistOfResultPath());
    EXPECT_FALSE(cpp_f.isExistOfResultPath());
    EXPECT_FALSE(java_f.isExistOfResultPath());

    Creat();

    OjLog::info("用户源文件存在, 符合预期");
    EXPECT_TRUE(c_f.isExistOfSourcePath());
    EXPECT_TRUE(cpp_f.isExistOfSourcePath());
    EXPECT_TRUE(java_f.isExistOfSourcePath());

    OjLog::info("用户目标文件不存在, 符合预期");
    EXPECT_FALSE(c_f.isExistOfObjectPath());
    EXPECT_FALSE(cpp_f.isExistOfObjectPath());
    EXPECT_FALSE(java_f.isExistOfObjectPath());

    OjLog::info("用户错误文件不存在, 符合预期");
    EXPECT_FALSE(c_f.isExistOfErrorPath());
    EXPECT_FALSE(cpp_f.isExistOfErrorPath());
    EXPECT_FALSE(java_f.isExistOfErrorPath());

    OjLog::info("用户结果文件不存在, 符合预期");
    EXPECT_FALSE(c_f.isExistOfResultPath());
    EXPECT_FALSE(cpp_f.isExistOfResultPath());
    EXPECT_FALSE(java_f.isExistOfResultPath());
}

TEST(OjClassTest, OjCompiler) {    
    using namespace ojlb::oj_common;
    using namespace ojlb::oj_compiler_run;
    
    Creat();

    OjLog::info("创建 OjCodeFile 对象");
    OjCodeFile c_f("./tests/user", "c");
    OjCodeFile cpp_f("./tests/user", "cpp");
    OjCodeFile java_f("./tests/User", "java");
    
    OjLog::info("使用虚拟编译器进行多语言编译, 同时检查编译结果为成功, 符合预期");
    EXPECT_TRUE(OjCompiler::compile(c_f));
    EXPECT_TRUE(OjCompiler::compile(cpp_f));
    EXPECT_TRUE(OjCompiler::compile(java_f));

    OjLog::info("等待之前的文件全部编译成功...");
    while (c_f.isExistOfObjectPath() == false || cpp_f.isExistOfObjectPath() == false || java_f.isExistOfObjectPath() == false) {
        OjLog::info("等待之前的文件全部编译成功...");
    }

    CreatComError();

    OjLog::info("重新编译用户提交的存在 bug 的代码导致编译失败, 符合预期");
    EXPECT_FALSE(OjCompiler::compile(c_f));
    EXPECT_FALSE(OjCompiler::compile(cpp_f));
    EXPECT_FALSE(OjCompiler::compile(java_f));

    OjLog::info("检查错误文件内容和给定内容相同, 符合预期");
    std::string c_err = R"(./tests/user.c:3:1: error: unknown type name ‘a’
    3 | a bug
      | ^
./tests/user.c:3:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ at end of input
)";
    std::string cpp_err = R"(./tests/user.cc:3:1: error: ‘a’ does not name a type
    3 | a bug
      | ^
)";
    std::string java_err = R"(./tests/User.java:2: error: class, interface, or enum expected
a bug
^
1 error
)";

    EXPECT_EQ(ReadFileToString(c_f.getErrorPath()), c_err);
    EXPECT_EQ(ReadFileToString(cpp_f.getErrorPath()), cpp_err);
    EXPECT_EQ(ReadFileToString(java_f.getErrorPath()), java_err);
}

TEST(OjClassTest, OjRuner) {
    using namespace ojlb::oj_common;
    using namespace ojlb::oj_compiler_run;

    // 模拟用户提交合法代码
    OjLog::info("模拟用户提交合法代码");
    
    Creat();

    OjLog::info("创建 OjCodeFile 对象");
    OjCodeFile c_f("./tests/user", "c");
    OjCodeFile cpp_f("./tests/user", "cpp");
    OjCodeFile java_f("./tests/User", "java");

    OjLog::info("尝试编译合法的代码, 编译通过, 符合预期");
    EXPECT_TRUE(OjCompiler::compile(c_f));
    EXPECT_TRUE(OjCompiler::compile(cpp_f));
    EXPECT_TRUE(OjCompiler::compile(java_f));

    OjLog::info("尝试运行合法的代码, 运行通过, 符合预期");
    std::pair<bool, int> c_res;
    std::pair<bool, int> cpp_res;
    std::pair<bool, int> java_res; 

    c_res = OjRuner::run(c_f);
    cpp_res = OjRuner::run(cpp_f);
    java_res = OjRuner::run(java_f);

    EXPECT_TRUE(c_res.first);
    EXPECT_TRUE(cpp_res.first);
    EXPECT_TRUE(java_res.first);

    EXPECT_EQ(c_res.second, 0);
    EXPECT_EQ(cpp_res.second, 0);
    EXPECT_EQ(java_res.second, 0);

    OjLog::info("比对运行结果成功, 符合预期");
    std::string c_out = R"(Hello, C User!)";
    std::string cpp_out = R"(Hello, Cpp User!)";
    std::string java_out = R"(Hello, Java User!)";

    EXPECT_EQ(ReadFileToString(c_f.getResultPath()), c_out);
    EXPECT_EQ(ReadFileToString(cpp_f.getResultPath()), cpp_out);
    EXPECT_EQ(ReadFileToString(java_f.getResultPath()), java_out);

    // 模拟用户提交运行错误代码
    CreatRunError();

    OjLog::info("尝试编译有运行异常的代码, 编译通过, 符合预期");
    EXPECT_TRUE(OjCompiler::compile(c_f));
    EXPECT_TRUE(OjCompiler::compile(cpp_f));
    EXPECT_TRUE(OjCompiler::compile(java_f));

    OjLog::info("尝试运行有运行异常的代码, 运行异常, 符合预期");
    c_res = OjRuner::run(c_f);
    cpp_res = OjRuner::run(cpp_f);
    java_res = OjRuner::run(java_f);
    
    EXPECT_FALSE(c_res.first);
    EXPECT_FALSE(c_res.first);
    EXPECT_FALSE(c_res.first);

    EXPECT_EQ(c_res.second, 8); // TODO: 而由于 C/Cpp 都是直接交给操作系统运行, 不是交给某个机器, 这就导致操作系统发出触发信号, 把信号发给子进程后就把子进程终止, 父进程获取到的就是最原生的信号信息, 浮点错误就是 8
    EXPECT_EQ(cpp_res.second, 8);
    EXPECT_EQ(java_res.second, 0); // TODO: Java 的解释器本身确实是运行成功了, 因此这里的判断等待后续进行修改

    // 模拟用户提交内存限制代码
    CreatMemoryLimited();

    OjLog::info("尝试编译有内存限制的代码, 编译通过, 符合预期");
    EXPECT_TRUE(OjCompiler::compile(c_f));
    EXPECT_TRUE(OjCompiler::compile(cpp_f));
    EXPECT_TRUE(OjCompiler::compile(java_f));

    OjLog::info("尝试运行有内存限制的代码, 运行异常, 符合预期");
    c_res = OjRuner::run(c_f, RLIM_INFINITY, 50 * 1024);
    cpp_res = OjRuner::run(cpp_f, RLIM_INFINITY, 50 * 1024);
    java_res = OjRuner::run(java_f, RLIM_INFINITY, 50 * 1024);
    
    OjLog::info("由于用户代码比较严格, 对申请内存的过程有处理, 因此即便运行异常也无法检测, 因此必然也是运行正确和 0 号信号");

    EXPECT_TRUE(c_res.first);
    EXPECT_TRUE(cpp_res.first);
    EXPECT_TRUE(java_res.first);

    EXPECT_EQ(c_res.second, 0);
    EXPECT_EQ(cpp_res.second, 0);
    EXPECT_EQ(java_res.second, 0);

    EXPECT_EQ(ReadFileToString(c_f.getErrorPath()), "malloc error");
    EXPECT_EQ(ReadFileToString(cpp_f.getErrorPath()), "Memory allocation failed: std::bad_alloc");
    OjLog::warn("Java 的内存异常暂时不测, 以后再说...");
    // EXPECT_EQ(ReadFileToString(java_f.getErrorPath()), "...");

    // 模拟用户提交处理限制代码
    CreatCpuLimited();
    OjLog::info("尝试编译有处理限制的代码, 编译通过, 符合预期");
    EXPECT_TRUE(OjCompiler::compile(c_f));
    EXPECT_TRUE(OjCompiler::compile(cpp_f));
    EXPECT_TRUE(OjCompiler::compile(java_f));

    OjLog::info("尝试运行有处理限制的代码, 因为实现机制和内存有点不一样, 可以检测出运行异常, 符合预期");
    c_res = OjRuner::run(c_f, 1, RLIM_INFINITY);
    cpp_res = OjRuner::run(cpp_f, 1, RLIM_INFINITY);
    java_res = OjRuner::run(java_f, 1, RLIM_INFINITY);
    
    EXPECT_FALSE(c_res.first);
    EXPECT_FALSE(cpp_res.first);
    EXPECT_FALSE(java_res.first);

    EXPECT_EQ(c_res.second, 24);
    EXPECT_EQ(cpp_res.second, 24);
    EXPECT_EQ(java_res.second, 24);
}

TEST(OjClassTest, OjCompileRun) {
    using namespace ojlb::oj_common;
    using namespace ojlb::oj_compiler_run;

    // 清理环境
    system("rm -rf ./title/double_pointer/limou3434_*");
    
    // 准备数据
    OjLog::info("创建一份 in_json");
    Json::Value in_json;
    in_json["user"] = "limou3434";
    in_json["title"] = "double_pointer";
    in_json["code"] = R"(#include <iostream>
int main() {
    std::cout << "Hello, I am limou3434.";
    return 0;
})";
    in_json["programming_language"] = "cpp";
    in_json["cpu_limit"] = -1;
    in_json["mem_limit"] = -1;

    OjLog::info("序列化 in_json 模拟网络请求交给服务器路由处理");
    std::string in_json_str;
    std::string out_json_str;

    // 测试正常请求
    OjLog::info("测试正常请求");
    OjTransfer::serialize(in_json, in_json_str);
    OjCompileRun::start(in_json_str, out_json_str);
    OjLog::info("获取响应 json 为 {}", out_json_str);

    // 额外检查运行结果
    OjLog::info("检查运行结果, 符合预期");
    Json::Value out_json;
    OjTransfer::deserialize(out_json_str, out_json);
    EXPECT_EQ(out_json["status"].asInt(), 0);
    std::string path = "./title/double_pointer/limou3434_";
    path += out_json["time_stamp"].asString();
    path += "_";
    path += out_json["id"].asString();
    path += ".ccres";
    EXPECT_EQ(ReadFileToString(path), "Hello, I am limou3434.");

    // 测试带有空代码的请求
    OjLog::info("测试带有空代码的请求");
    in_json["code"] = "";
    OjTransfer::serialize(in_json, in_json_str);
    OjCompileRun::start(in_json_str, out_json_str);
    OjLog::info("获取响应 json 为 {}", out_json_str);
    OjTransfer::deserialize(out_json_str, out_json);
    EXPECT_EQ(out_json["status"].asInt(), 1);

    // 测试带有编译失败的请求
    OjLog::info("测试带有编译失败的请求");
    in_json["code"] = R"(#include <iostream>
int main() {
    std::cout << "Hello, I am
    return 0;
})";
    OjTransfer::serialize(in_json, in_json_str);
    OjCompileRun::start(in_json_str, out_json_str);
    OjLog::info("获取响应 json 为 {}", out_json_str);
    OjTransfer::deserialize(out_json_str, out_json);
    EXPECT_EQ(out_json["status"].asInt(), 2);

    // 测试带有运行异常的请求
    OjLog::info("测试带有运行异常的请求");
    in_json["code"] = R"(#include <iostream>
int main() {
    int a = 1;
    int b = 0;
    int c = a / b;
    return 0;
})";
    OjTransfer::serialize(in_json, in_json_str);
    OjCompileRun::start(in_json_str, out_json_str);
    OjLog::info("获取响应 json 为 {}", out_json_str);
    OjTransfer::deserialize(out_json_str, out_json);
    EXPECT_EQ(out_json["status"].asInt(), 3);
}

TEST(OjClassTest, OjServer) {
    using namespace ojlb::oj_common;
    using namespace ojlb::oj_server;
    OjLog::info("开始运行服务");
    OjServer(8080, "0.0.0.0");
}

int main(int argc, char** argv) {
    using namespace ojlb::oj_common;
    OjLog::setShieldLevel("trace");
    OjLog::info("启动测试项目");
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
